package fr.gedos.ged.analyser.recognition.adapter.beans;

import java.awt.Rectangle;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import fr.gedos.ged.analyser.recognition.adapter.exceptions.PictureNotWellWritingException;
import fr.gedos.ged.analyser.recognition.adapter.interfaces.ImageSplitter;
import fr.gedos.ged.analyser.recognition.adapter.interfaces.OCRRecognitionModule;


/**
 * This class permit to launch OCR Recognition on a file, and set different search areas to extract
 * words. Caution: tesseract must be installed and in path (external call to it). You must install
 * the well language file for tesseract to get good results. Test Language: english
 * 
 * @author rastafire
 * 
 */
public class TesseractOCRConnector implements OCRRecognitionModule {

    private static final String WHITE_SPACE = " ";

    private static final String TESSERACT_CALL = "tesseract ";

    /** The file we want to analyse. */
    private File currentPictureFile;

    /** The splitter which will extract SubImage on which we'll call tesseract. */
    private ImageSplitter splitter;

    /**
     * The list of areas we must analyse. The classifier is responsible to set this attribute for
     * us.
     */
    private List<Rectangle> areasToAnalyse;

    /**
     * Simple constructor.
     * 
     * @param currentPictureFile
     *            - The file on which extract words
     * @param splitter
     *            - An ImageSplitter object to extract sub areas from original picture File
     */
    public TesseractOCRConnector(File currentPictureFile, ImageSplitter splitter) {
        super();
        this.currentPictureFile = currentPictureFile;
        this.splitter = splitter;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * fr.gedos.ged.classifier.recognition.adapter.interfaces.OCRRecognitionModule#prepareSubPicture
     * (java.awt.Rectangle)
     */
    public File prepareSubPicture(Rectangle area) throws IOException,
            PictureNotWellWritingException {
        return splitter.getSubPicture(currentPictureFile, area);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * fr.gedos.ged.classifier.recognition.adapter.interfaces.OCRRecognitionModule#launchOCR(java
     * .io.File)
     */
    public List<String> launchOCR(File fileToExtractWords) throws IOException,
            PictureNotWellWritingException, InterruptedException {
        currentPictureFile = fileToExtractWords;

        List<String> result = new ArrayList<String>();
        if (areasToAnalyse.size() == 0) {
            result.add(launchTesseractOnSubPicture(currentPictureFile));
        } else {
            // for each area, we launch an OCR tool on subImage and we get the list of words in it.
            for (Rectangle currentZone : areasToAnalyse) {
                File subPicture = prepareSubPicture(currentZone);
                result.add(launchTesseractOnSubPicture(subPicture));
            }
        }
        return result;
    }

    /**
     * Permit to an external object to set Areas on which extract words.
     * 
     * @param areasToAnalyse
     *            - The list of search areas
     */
    public void setAreasToAnalyse(List<Rectangle> areasToAnalyse) {
        this.areasToAnalyse = areasToAnalyse;
    }

    /**
     * Launch tesseract on command line to extract words from a file.
     * 
     * @param subPicture
     *            - The file we want to launch OCR Recognition on
     * @return - words extracted by tesseract
     * @throws IOException
     * @throws InterruptedException
     */
    private String launchTesseractOnSubPicture(File subPicture) throws IOException,
            InterruptedException {
        Process p = Runtime.getRuntime().exec(
                TESSERACT_CALL + subPicture.getAbsolutePath() + WHITE_SPACE
                        + subPicture.getAbsolutePath());
        p.waitFor();

        String resultOfOCR = "";

        BufferedReader reader = new BufferedReader(new FileReader(new File(
                subPicture.getAbsolutePath() + ".txt")));
        String currentLine = "";
        while ((currentLine = reader.readLine()) != null) {
            resultOfOCR += currentLine + "\n";
        }

        return resultOfOCR;
    }
}
